package org.gitman.agent.platform;

import java.awt.Color;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import com.mxgraph.analysis.mxConstantCostFunction;
import com.mxgraph.analysis.mxGraphAnalysis;
import com.mxgraph.analysis.mxICostFunction;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxICell;
import com.mxgraph.view.mxGraph;
import com.mxgraph.view.mxGraph.mxICellVisitor;

public abstract class Agent{
	
	protected String description;
	protected String name;
	protected Color color;
	protected mxICell startPoint;
	protected mxICell endPoint;
	protected mxICell currentPoint;
	protected Simulation simulation;
	protected int iteration;
	protected AgentState state;


	/**	
	 * should return new instance of this agent
	 */
	public abstract Agent getInstance();
	/**
	 * do step can call on agentManager send message, should return vertex where this agent
	 * want move to, agent manager will then calculate if it can move there and then change 
	 * this agent currentPoint or leave there, if agent don't want just return its currentPoint
	 */
	public abstract mxICell doStep(mxGraph graph, AgentManager agentManager);
	
	public void handleMessage(Object message, Agent sender){
		logInfo(" gets message from " + sender.toString() + " : " + message.toString());
	}
	public mxICell getStartPoint() {
		return startPoint;
	}
	public void setStartPoint(mxICell startPoint) {
		this.startPoint = startPoint;
	}
	public mxICell getEndPoint() {
		return endPoint;
	}
	public void setEndPoint(mxICell endPoint) {
		this.endPoint = endPoint;
	}
	public mxICell getCurrentPoint() {
		return currentPoint;
	}
	public void setCurrentPoint(mxICell currentPoint) {
		this.currentPoint = currentPoint;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDescription(){
		return description;
	}
	public String getName(){
		return name;
	}
	public void setColor(Color color){
		this.color = color;
	}
	public Color getColor(){
		return color;
	}
	public void logInfo(String message){
		simulation.appendLog(message, this);
	}
	public void setSimulation(Simulation simulation) {
		this.simulation = simulation;		
	}
	@Override
	public String toString() {
		return "[" + color.getBlue() + "#" +  getName() + "]";
	}
	public boolean canReachTarget(mxGraph graph){
		return canReachTargetFrom(graph, currentPoint);
	}
	public boolean reachTarget() {
		return endPoint.equals(currentPoint);
	}
	public int getIteration() {
		return iteration;
	}
	public void setIteration(int iteration) {
		this.iteration = iteration;
	}	
	public boolean canReachTargetFrom(mxGraph graph, mxICell from){
		boolean can = false;
		mxICostFunction cf = new mxConstantCostFunction(1); 
		Object[] v = graph.getChildVertices(graph.getDefaultParent()); 
		mxGraphAnalysis mga = mxGraphAnalysis.getInstance();
		Object[] path = mga.getShortestPath(graph, from, endPoint, cf, v.length, true);
		if(path.length !=0){
			can = true;
		}
		return can;
	}
	public AgentState getState() {
		return state;
	}
	public void setState(AgentState state) {
		this.state = state;
	}
	public Simulation getSimulation() {
		return simulation;
	}
}
